package xiaojian.toolkit.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;

import xiaojian.toolkit.base.Sender;
import xiaojian.toolkit.base.TransportUtils;

public abstract class AbstractCommReqHandler<Q extends AbstractRequest, R extends AbstractResponse>
		extends AbstractReqHandler<AbstractRequest> {

	private static final Logger logger = LoggerFactory.getLogger(AbstractCommReqHandler.class);

	/**
	 * 要求子类生成一个回应对象。
	 * 
	 * @param request
	 * @return
	 */
	protected abstract R newResponse(Q request);

	/**
	 * @see com.wasu.upm.commons.handler.ReqHandler#doReq(com.wasu.upm.commons.AbstractUPMRequest)
	 */
	protected abstract void doReq1(Q request, R response);

	/**
	 * 让子类去处理处理过程中异常。
	 * 
	 * @param exception
	 */
	protected abstract void processException(Exception exception, Q request, R response);

	/**
	 * @see com.wasu.upm.commons.handler.ReqHander#doReq(com.wasu.upm.commons.
	 *      AbstractUPMRequest)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void doReq0(AbstractRequest request) {
		Preconditions.checkArgument(request != null && request.getIdentification() != null);

		logger.debug("Start process request[{}].", request);

		AbstractResponse response = newResponse((Q) request);

		if (response == null) {
			logger.error("Pls implement method[newResponse(AbstractRequest request)], request[" + request + "].");
			return;
		}

		try {
			doReq1((Q) request, (R) response);
		} catch (Exception exception) {
			logger.error("Prorcess reqest[" + request + "] fail.", exception);
			processException(exception, (Q) request, (R) response);

		}

		try {
			send(request, response);
		} catch (Throwable t) {
			logger.error("Send response fail, request[" + request + "].", t);
		}

	}

	protected void send(AbstractRequest request, AbstractResponse response) {
		response.setIdentification(request.getIdentification());
		Sender<AbstractResponse> sender = TransportUtils.getSenderOf(request);
		if (logger.isDebugEnabled()) {
			logger.debug("SendClientRespState={}", response);
		}
		if (sender != null) {
			sender.send(request, response);
		} else {
			logger.error("getSender error!");
		}
	}

}
